home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 1
/
Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso
/
FILES
/
DEV
/
A-B
/
Anim Cursor.cpt
/
CursorCtl.c
< prev
Wrap
Text File
|
1990-01-24
|
9KB
|
325 lines
/************************************************************************/
/* */
/* Cursor Control routines */
/* */
/* -- THINK C (V 4.0) version by Eric H. Seale, 1/23/90 */
/* */
/* Based on Lightspeed Pascal code by Chris Reed of San Angelo, */
/* TX, and Yasser Farra of Austin, TX */
/* */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* */
/* CREDITS: */
/* */
/* Chris Reed -- original idea, simple implementation */
/* */
/* Yasser Farra -- improved exception handling, remove use of */
/* buggy "SetUpA5" & "RestoreA5" routines (see tech note */
/* 208), animation speed and "acur" resource ID are now */
/* parameters */
/* */
/* Eric Seale -- translate to THINK C (from Lightspeed Pascal), */
/* "flesh out" the documentation */
/* */
/************************************************************************/
#include <VRetraceMgr.h>
/************************************************************************/
/* */
/* Define some new data types to handle the cursor frames */
/* */
/************************************************************************/
typedef struct {
int frameCount; /* number of frames in animation sequence */
int whichFrame; /* current frame number */
CursHandle frame[]; /* list of "CURS" resources */
} acur;
typedef acur *acurPtr;
typedef acurPtr *acurHandle;
/************************************************************************/
/* */
/* Define some "global" variables for our use */
/* */
/************************************************************************/
acurHandle frameList; /* handle to "acur" resource */
VBLTask cursVBL; /* VBL task to handle cursor animation */
Boolean cursAnimationEnabled, /* able to load "acur" and "CURS" rsrc's */
cursAlreadyOn; /* cursor animation already running */
int cursSpeed; /* # ticks between consec. frames */
/************************************************************************/
/* */
/* Function Prototypes for our code here */
/* */
/************************************************************************/
pascal long NuSetUpA5(void);
pascal long NuRestoreA5(long);
SetWatchCursor(void);
InitCursAnimation (int);
CursorAnimationVBL(void);
AnimateCursor (int);
StopCursor(void);
pascal long NuSetUpA5(void)
/************************************************************************/
/* */
/* pascal long NuSetUpA5(void) */
/* -- This routine sets up the A5 to point to the boundary */
/* between the application globals and the application */
/* parameters. It returns the previous value of A5. This */
/* function is used instead of SetUpA5 which is dangerous as it */
/* does not return the old value of A5 but rather leaves it on */
/* the stack--see tech note #208 for more details */
/* */
/* Note that both the Tech Note and Yasser's Pascal code called this */
/* routine "SetCurrentA5" -- it seemed that since this replaces the */
/* routine "SetUpA5," a more "intuitively obvious" name could be used */
/* (makes life easier for those used to the old names). Also, note */
/* that the assembler "equivalents" for the inline code are from */
/* Apple's Tech Note -- I'm no assembly language whiz, so I can't */
/* vouch for its accuracy (I just know that the hex works fine). */
/* */
/************************************************************************/
= {
0x2E8D, /* move.l a5, 4(a7) */
0x2A78, /* move.l currentA5, a5 */
0x0904 /* rts */
};
pascal long NuRestoreA5(long newA5)
/************************************************************************/
/* */
/* pascal long NuRestoreA5(long) */
/* -- This routine sets the value of A5 to "newA5". It should be */
/* used to restore the old value of A5 at the end of a */
/* completion routine or a VBL task. It also returns the */
/* previous value of A5. This function is used instead of */
/* RestoreA5 which assumes the old value of A5 is still on the */
/* stack--see tech note #208 for more details */
/* */
/* Note that both the Tech Note and Yasser's Pascal code called this */
/* routine "SetA5" -- change the name back if you'd like. */
/* */
/************************************************************************/
= {
0x2F4D, /* move.l (a7)+a0 */
0x0004, /* move.l a5, 4(a7) */
0x2A5F /* move.l (a7)+, a5 */
}; /* jmp.l (a0) */
SetWatchCursor()
/************************************************************************/
/* */
/* SetWatchCursor(void) */
/* -- set cursor to standard "watch" (cursor animation is disabled)*/
/* */
/************************************************************************/
{
CursHandle myCursor;
myCursor = GetCursor(watchCursor);
SetCursor(*myCursor);
}
InitCursAnimation(acurID)
int acurID; /* RSRC ID of "acur" resource */
/************************************************************************/
/* */
/* InitCursAnimation(int) */
/* -- This procedure tries to load the "acur" resource and if */
/* found tries to load all the "CURS" resources listed in the */
/* "acur" resource */
/* */
/************************************************************************/
{
int i,
errorCode;
/* Get the "acur" resource */
frameList = (acurHandle)GetResource('acur', acurID);
errorCode = ResError();
if (frameList == 0L) errorCode = resNotFound;
if (errorCode == noErr) {
i = 0;
while ((i < (**frameList).frameCount) && (errorCode == noErr)){
/* Get the "CURS" resources whose ID's are in the high word */
/* of the frame field. Store handle to these resources in */
/* the same frame field */
(**frameList).frame[i] =
GetCursor( HiWord((long)((**frameList).frame[i])) );
errorCode = ResError();
if ((**frameList).frame[i] == 0L)
errorCode |= resNotFound;
i++;
}
(**frameList).whichFrame = 1; /* Set initial frame */
}
cursAnimationEnabled = (errorCode == noErr);/* True if no error found */
}
CursorAnimationVBL()
/************************************************************************/
/* */
/* CursorAnimationVBL(void) */
/* -- VBL routine to set the cursor to the next cursor in the */
/* animation sequence */
/* */
/************************************************************************/
{
long oldA5;
oldA5 = NuSetUpA5();
/* frameList and all frame handles are assumed to be locked */
SetCursor(*((**frameList).frame[(**frameList).whichFrame]));
if (++(**frameList).whichFrame >= (**frameList).frameCount)
(**frameList).whichFrame = 1;
cursVBL.vblCount = cursSpeed; /* Reinstall the VBL */
oldA5 = NuRestoreA5(oldA5);
}
AnimateCursor(speed)
int speed; /* Ticks between consecutive frames */
/************************************************************************/
/* */
/* AnimateCursor(int) */
/* -- Install our task in the vertical retrace queue unless cursor */
/* animation is not enabled then use watch cursor */
/* */
/************************************************************************/
{
int errorcode, i;
if (!cursAlreadyOn) {
cursAlreadyOn = TRUE;
if (cursAnimationEnabled) {
/* Lock all handles that will be accessed from the VBL */
HLock((Handle)(frameList));
for (i=0; i<(**frameList).frameCount; i++)
HLock((Handle)((**frameList).frame[i]));
(**frameList).whichFrame = 1; /* Set initial frame */
/* Set up the VBL task fields and install it */
cursVBL.qType = vType;
cursVBL.vblAddr = &CursorAnimationVBL;
cursVBL.vblCount = speed; /* next VBL after "speed" ticks */
cursVBL.vblPhase = 0;
errorcode = VInstall(&cursVBL);
cursSpeed = speed; /* Set the speed of animation */
}
else /* Use watch cursor */
SetWatchCursor();
}
}
StopCursor()
/************************************************************************/
/* */
/* StopCursor(void) */
/* -- Remove the VBL task from the vertical retrace queue and */
/* restore the arrow cursor */
/* */
/************************************************************************/
{
int errorCode, i;
if (cursAlreadyOn) {
cursAlreadyOn = FALSE;
if (cursAnimationEnabled) {
errorCode = VRemove(&cursVBL);
/* Unlock all handles that were locked before VBL */
/* installation */
HUnlock((Handle)(frameList));
for (i = 0; i< (**frameList).frameCount; i++)
HUnlock((Handle)((**frameList).frame[i]));
}
InitCursor();
}
}